package My

import (
	"context"
	"errors"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"db2s/go-log/log"
	"db2s/parDef"
	"db2s/ref"
	"reflect"
	"strings"
)

func (pm PartitionMe) PartType(ctx context.Context) (result global.Return, err error) {
	var event = "[PartType]"
	defer func() { err = ref.RecoverPanic(event, recover()) }()
	select {
	case <-ctx.Done():
		err = ctx.Err()
		return
	default:
		if result, err = parDef.SqlExec(parDef.GetSqlQueryExecFuncParameterValue(ctx, event, partitionTableSysObjectView, getTablePartitionTypeMetaSql,QueryColValManage)); err != nil {
			log.ErrorLog().Error(event, getTableName(parDef.GetExecFuncParameterValueBase(ctx)), fmt.Sprintf(" sql is %v, error is %v.", result.Sql, err))
			return
		}
	}
	return
}
func (pm PartitionMe) PartSum(ctx context.Context) (result global.Return, err error) {
	var event = "[PartSum]"
	defer func() { err = ref.RecoverPanic(event, recover()) }()
	select {
	case <-ctx.Done():
		err = ctx.Err()
		return
	default:
		if result, err = parDef.SqlExec(parDef.GetSqlQueryExecFuncParameterValue(ctx, event, partitionTableSysObjectView, getTablePartitionSumMetaSql,QueryColValManage)); err != nil {
			log.ErrorLog().Error(event, getTableName(parDef.GetExecFuncParameterValueBase(ctx)), fmt.Sprintf(" sql is %v, error is %v.", result.Sql, err))
			return
		}
	}
	return
}

func (pm PartitionMe) getPartBaseMeta(ctx context.Context) (result global.Return, err error) {
	var event = "[getPartBaseMeta]"
	defer func() { err = ref.RecoverPanic(event, recover()) }()
	select {
	case <-ctx.Done():
		err = ctx.Err()
		return
	default:
		if result, err = parDef.SqlExec(parDef.GetSubSqlExecFuncParameterValue(ctx, event, ETL.SMap, partitionTableSysObjectView, getTablePartitionMetaSql,QueryColValManage)); err != nil {
			log.ErrorLog().Error(event, getTableName(parDef.GetExecFuncParameterValueBase(ctx)), fmt.Sprintf(" sql is %v, error is %v.", result.Sql, err))
			return
		}
		if result.Result == nil {
			return
		}
		var res []map[string]any
		for _, v := range result.Result.([]map[string]interface{}) {
			res = append(res, mapNullActive(v))
		}
		result.Result = res
	}
	return
}
func (pm PartitionMe) getFirstPartColumn(par any) (result []string, err error) {
	var partCol []string
	var partColMap = make(map[string]int)
	switch par.(type) {
	case []map[string]any:
		for _, v := range par.([]map[string]any) {
			k, _ := v["firstPartColumn"]
			key := strings.ReplaceAll(fmt.Sprintf("%v", k), "\"", "")
			key = strings.ReplaceAll(key, "`", "")
			if _, ok := partColMap[fmt.Sprintf("%v", k)]; !ok {
				partCol = strings.Split(key, ",")
				partColMap[fmt.Sprintf("%v", k)]++
			}
		}
	default:
		err = ref.ErrAddPrintf("getFirstPartColumn", errors.New(fmt.Sprintf("type is not match. curry type is %v", reflect.TypeOf(par))))
	}
	result = partCol
	return
}
func (pm PartitionMe) getSubPartColumn(par any) (result []string, err error) {
	var partCol []string
	var partColMap = make(map[string]int)
	switch par.(type) {
	case []map[string]any:
		for _, v := range par.([]map[string]any) {
			k, _ := v["subPartColumn"]
			key := strings.ReplaceAll(fmt.Sprintf("%v", k), "\"", "")
			key = strings.ReplaceAll(key, "`", "")
			if _, ok := partColMap[fmt.Sprintf("%v", k)]; !ok {
				partCol = strings.Split(key, ",")
				partColMap[fmt.Sprintf("%v", k)]++
			}
		}
	default:
		err = ref.ErrAddPrintf("getSubPartColumn", errors.New(fmt.Sprintf("type is not match. curry type is %v", reflect.TypeOf(par))))
	}
	result = partCol
	return
}
func (pm PartitionMe) getPartMeth(par any) (result parDef.PartMeth, err error) {
	result.First = "NULL"
	result.Sub = "NULL"
	switch par.(type) {
	case []map[string]any:
		for _, v := range par.([]map[string]any) {
			f, _ := v["firstPartMeth"]
			s, _ := v["subPartMeth"]
			result.First = strings.TrimSpace(strings.ReplaceAll(fmt.Sprintf("%v", f), "COLUMNS", ""))
			result.Sub = strings.TrimSpace(strings.ReplaceAll(fmt.Sprintf("%v", s), "COLUMNS", ""))
		}
	default:
		err = ref.ErrAddPrintf("getPartMeth", errors.New(fmt.Sprintf("type is not match. curry type is %v", reflect.TypeOf(par))))
		return
	}
	return
}
func (pm PartitionMe) LegalTypeCheck(par any) (result []map[string]any) {
	switch par.(type) {
	case []map[string]any:
		result = par.([]map[string]any)
	}
	return
}
func (pm PartitionMe) getFirstSubPartRuleSplit(par any) (partRuleMap []map[string]any, SubPartMap map[string][]map[string]any) {
	SubPartMap = make(map[string][]map[string]any)
	for _, v := range pm.LegalTypeCheck(par) {
		var key = fmt.Sprintf("%v", v["firstPartName"])
		var p = make(map[string]any)
		p["partName"] = v["firstPartName"]
		p["rules"] = v["partitionRules"]
		p["seq"] = v["firstPartSeq"]
		p["subSeq"] = v["subPartSeq"]
		p["subPartName"] = fmt.Sprintf("%v", v["subPartName"])
		if pp, ok := SubPartMap[key]; !ok {
			partRuleMap = append(partRuleMap, p)
			SubPartMap[key] = []map[string]any{p}
		} else {
			pp = append(pp, p)
		}
	}
	return
}
func (pm PartitionMe) getPartRule(par any) (result []parDef.PartRule, err error) {
	var newPartRuleMap []parDef.PartRule
	partRuleMap, SubPartMap := pm.getFirstSubPartRuleSplit(par)
	for _, v := range partRuleMap {
		delete(v, "subSeq")
		var key = fmt.Sprintf("%v", v["partName"])
		v["subSum"] = fmt.Sprintf("%v", len(SubPartMap[key]))
		var rule parDef.PartRule
		if err = ref.MapToStruct(v, &rule); err != nil {
			err = ref.ErrAddPrintf("getPartRule", err)
			return
		}
		newPartRuleMap = append(newPartRuleMap, rule)
	}
	result = newPartRuleMap
	return
}
func (pm PartitionMe) getSubPartRule(par any) (result []parDef.PartRule, err error) {
	var newPartRuleMap []parDef.PartRule
	partRuleMap, SubPartMap := pm.getFirstSubPartRuleSplit(par)
	for _, part := range partRuleMap {
		var key = fmt.Sprintf("%v", part["partName"])
		if sub, ok := SubPartMap[key]; ok {
			for _, v := range sub {
				v["rules"] = "NULL"
				v["seq"] = v["subSeq"]
				delete(v, "subSeq")
				var rule parDef.PartRule
				if err = ref.MapToStruct(v, &rule); err != nil {
					err = ref.ErrAddPrintf("getSubPartRule", err)
					return
				}
				newPartRuleMap = append(newPartRuleMap, rule)
			}
		}
	}
	result = newPartRuleMap
	return
}
func (pm PartitionMe) newPartMetaBaseInit(ctx context.Context) (result parDef.PartMetaData, err error) {
	var res global.Return
	if res, err = pm.getPartBaseMeta(ctx); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	if res.Result == nil {
		return
	}
	if result.RuleDesc, err = pm.getPartRule(res.Result); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	if result.SubPartDesc, err = pm.getSubPartRule(res.Result); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	if result.Meth, err = pm.getPartMeth(res.Result); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	if result.PartCol, err = pm.getFirstPartColumn(res.Result); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	if result.SubPartCol, err = pm.getSubPartColumn(res.Result); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	}
	return
}
func (pm PartitionMe) PartMeta(ctx context.Context) (result global.Return, err error) {
	var baseResult parDef.PartMetaData
	var partName []string
	if baseResult, err = pm.newPartMetaBaseInit(ctx); err != nil {
		err = ref.ErrAddPrintf("PartMeta", err)
		return
	}
	for _, v := range baseResult.RuleDesc {
		partName = append(partName, v.Name)
	}
	baseResult.PartName = partName
	result.Result = baseResult
	return
}

func (pm PartitionMe) NameToRuleClip(ctx context.Context) (result global.Return, err error) {
	return
}
